/*
 *
 * Copyright (c) 2020 The Raptor Authors. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#ifndef RAPTOR_LITE_SRC_COMMON_ENDPOINT_IMPL_H_
#define RAPTOR_LITE_SRC_COMMON_ENDPOINT_IMPL_H_

#include <stddef.h>
#include <stdint.h>
#include <memory>

#include "raptor-lite/utils/slice.h"
#include "src/common/resolve_address.h"

namespace raptor {
class Container;

class EndpointImpl final : public std::enable_shared_from_this<EndpointImpl> {
    friend class Connection;

public:
    EndpointImpl(uint64_t fd, raptor_resolved_address *local, raptor_resolved_address *remote);
    ~EndpointImpl();

    void SetConnectionId(uint32_t connection_id);
    void SetContainer(Container *container);
    void SetListenPort(uint16_t port);

    inline std::shared_ptr<EndpointImpl> GetEndpointImpl() { return this->shared_from_this(); }

    // If attached to the container, it returns a valid value.
    uint32_t ConnectionId();

    // don't close it
    uint64_t SocketFd();
    uint16_t GetListenPort();

    std::string PeerString();
    std::string LocalString();

    // Give the endpoint to the container management.
    // It means that the data receiving and sending work
    // is handed over to the container to complete.
    void BindContainer(Container *container);

    bool SendMsg(const Slice &slice);
    bool SendMsg(const void *data, size_t len);

    // Used directly, not bind with the container
    int SyncRecv(void *data, size_t len);
    int SyncSend(const void *data, size_t len);

    bool Close(bool notify);

    std::string LocalIp();
    uint16_t LocalPort();
    std::string RemoteIp();
    uint16_t RemotePort();

    bool IsValid();
    void SetPrivateContext(intptr_t ctx);
    intptr_t PrivateContext();

private:
    uint64_t fd_;
    uint32_t connection_id_;
    Container *container_;
    uint16_t listen_port_; // for server
    uintptr_t private_ctx_;
    raptor_resolved_address local_;
    raptor_resolved_address remote_;
};

} // namespace raptor

#endif // RAPTOR_LITE_SRC_COMMON_ENDPOINT_IMPL_H_
